#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import os
import signal
import psutil

from common.common_models import SubJobModel
from common.parse_parafile import ParamFileUtil
from exchange import log
from exchange.commons.const import ExchangeJobInfo, SubJobType, TaskStage
from exchange.commons.exchange_function_tool import log_start_end
from exchange.commons.exchange_param_parse import ExchangeParamParse


class ExchangeBackupAbortJob:
    def __init__(self, pid):
        self._pid = pid
        self._param = ParamFileUtil.parse_param_file(pid)

    @staticmethod
    def build_sub_job(job_priority, policy, job_name, node_id, job_info: ExchangeJobInfo):
        return SubJobModel(jobId=job_info.job_id, jobType=SubJobType.BUSINESS_SUB_JOB.value, execNodeId=node_id,
                           jobPriority=job_priority, jobName=job_name, policy=policy,
                           ignoreFailed=False).dict(by_alias=True)

    @log_start_end()
    def do_abort_job(self, job_info: ExchangeJobInfo):
        log.info(f'execute to abort_job, job_id:{job_info.job_id}, sub_job_id:{job_info.sub_job_id}')
        if job_info.job_id is None or len(job_info.job_id) == 0:
            return True
        processes = psutil.process_iter()
        for process in processes:
            cmd_lines = process.cmdline()
            if len(cmd_lines) < 5:
                continue
            if str(job_info.job_id) == str(cmd_lines[4]) and (
                    str(cmd_lines[2]) in [TaskStage.BACKUP_PREREQUISITE, TaskStage.BACKUP_GEN_SUB_JOB,
                                          TaskStage.BACKUP]):
                # windows下没有SIGKILL, 使用SIGTERM
                os.kill(process.pid, signal.SIGTERM)
                log.info(
                    f"exchange dag backup kill pid: {process.pid} for job id:\
                     {job_info.job_id} in stage: {cmd_lines[2]}")
                # 无需清理数据，在后置任务中处理
                log.info(f"exchange dag backup abort job success")
                break
        return True

    def get_job_info(self):
        job_info = ExchangeJobInfo(pid=self._pid,
                                   job_id=ExchangeParamParse.get_job_id(self._param),
                                   sub_job_id=ExchangeParamParse.get_sub_job_id(self._param),
                                   copy_id=ExchangeParamParse.get_copy_id(self._param),
                                   backup_type=ExchangeParamParse.get_type(self._param),
                                   meta_path=ExchangeParamParse.get_meta_path(self._param),
                                   data_reps=ExchangeParamParse.get_data_reps(self._param),
                                   cache_path=ExchangeParamParse.get_cache_path(self._param),
                                   backup_result=ExchangeParamParse.get_backup_result(self._param))
        return job_info
